package com.xujl.task.delegate;

import com.xujl.task.Emitter;
import com.xujl.task.RxExecutor;
import com.xujl.task.RxLife;
import com.xujl.task.RxLog;
import com.xujl.task.Task;
import com.xujl.task.TaskUtils;
import com.xujl.task.consts.TaskRetry;

import java.util.concurrent.Future;

import androidx.annotation.CallSuper;

/**
 * 抽象任务代理
 */
public class AbstractTaskDelegate<T> implements RxLife {
    protected static final String TAG = "AbstractTaskDelegate";

    protected Emitter<T> mEmitter;
    protected Future<T> mFuture;
    protected boolean isDestroy;
    /**
     * 绑定生命周期时是否需要在
     * 生命周期结束后取消任务
     * 设置为true时（任务可能执行到一半就会结束
     * ，慎重设置！）
     */
    protected boolean needCancel;

    protected Task<T> mTask;
    /**
     * 失败重试最大次数
     */
    protected int retryMaxCount = TaskRetry.NONE;
    /**
     * 当前重试次数
     */
    protected int retryCount;
    /**
     * 是否强绑定
     */
    private boolean isForceBind;
    /**
     * 任务执行状态
     */
    private String taskState = Task.STATE_DEFAULT;

    public AbstractTaskDelegate (Task<T> task, boolean needCancel) {
        mTask = task;
        mTask.setTaskId(TaskUtils.createTaskId());
        RxLog.d(TAG, "task创建：" + mTask.getTaskId());
        mEmitter = new Emitter<>(task, mTask.getTaskId());
        this.needCancel = needCancel;
        isForceBind = mTask.bindLife(this);
    }

    /**
     * 生命周期结束后，子线程任务依然会执行
     * 完毕，但不会再回调结果,如果需要及时停止
     * 子线程任务，请在子线程任务中根据方法isDestroy()
     * 加以判断
     */
    public void onDestroy () {
        isDestroy = true;
        if (getEmitter() == null) {
            return;
        }
        setTaskState(Task.STATE_DESTROY);
        mTask.deleteObservers();
        if (mFuture != null && needCancel) {
            mFuture.cancel(true);
        }
        if (isForceBind) {
            return;
        }
        mEmitter = null;
        mTask.recycle();
        mTask = null;
        setFuture(null);
    }


    /**
     * 解除绑定关系
     */
    @Override
    public void doUnbind () {
        isForceBind = false;
        onDestroy();
    }

    @Override
    public boolean isDestroy () {
        return isDestroy;
    }


    /**
     * 主线程回调
     *
     * @param e
     */
    public void onError (Exception e) {
        if (retryMaxCount == TaskRetry.NONE) {
            onDestroy();
            return;
        }
        if (retryMaxCount != TaskRetry.INFINITE && retryCount >= retryMaxCount) {
            RxLog.d(TAG, "超过最大重试次数！任务失败，结束");
            onDestroy();
            return;
        }
        retryCount++;
        RxLog.d(TAG, "任务失败，重试第" + retryCount + "次！");
        reset();
        RxExecutor.getInstance().executeTask(mTask);
    }

    /**
     * 主线程回调
     */
    @CallSuper
    public void onFinished () {
        onDestroy();
    }

    /**
     * 取消任务
     * 只能是停掉线程中有sleep,wait,join逻辑的线程，抛出一个InterruptException
     *
     * @param interrupt
     * @return
     */
    public boolean cancel (boolean interrupt) {
        if (mFuture == null) {
            return false;
        }
        return mFuture.cancel(interrupt);
    }

    public void reset () {
        if (getTaskState().equals(Task.STATE_DEFAULT)) {
            return;
        }
        mEmitter = new Emitter<>(mTask, mTask.getTaskId());
        isForceBind = mTask.bindLife(this);
        isDestroy = false;
        setTaskState(Task.STATE_DEFAULT);
    }

    public Future<T> getFuture () {
        return mFuture;
    }

    public void setFuture (Future<T> future) {
        mFuture = future;
    }

    public boolean isNeedCancel () {
        return needCancel;
    }

    public void setNeedCancel (boolean needCancel) {
        this.needCancel = needCancel;
    }


    public Emitter getEmitter () {
        return mEmitter;
    }

    @Override
    public boolean equals (Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode () {
        return super.hashCode();
    }



    public int getRetryMaxCount () {
        return retryMaxCount;
    }

    public void setRetryMaxCount (int retryMaxCount) {
        this.retryMaxCount = retryMaxCount;
    }

    public boolean canRetry () {
        if (retryMaxCount == TaskRetry.INFINITE) {
            return true;
        }
        return retryMaxCount != TaskRetry.NONE && retryCount < retryMaxCount;
    }

    public int getRetryCount () {
        return retryCount;
    }

    public void setDestroy (boolean destroy) {
        isDestroy = destroy;
    }

    public String getTaskState () {
        return taskState;
    }

    public void setTaskState (String taskState) {
        this.taskState = taskState;
        mTask.notifyObservers(taskState);
    }
}
